/*=============================================================================
PostProcessWater : water related post processing
Copyright (c) 2001 Crytek Studios. All Rights Reserved.

Revision history:
* 23/02/2005: Re-factored/Converted to CryEngine 2.0 by Tiago Sousa
* Created by Tiago Sousa

=============================================================================*/

#include "StdAfx.h"
#include "DriverD3D.h"
#include "I3DEngine.h"
#include "D3DPostProcess.h"

#pragma warning(disable: 4244)


////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CUnderwaterGodRays::Render()
{
  PROFILE_LABEL_PUSH( "GODRAYS" );

  PROFILE_SHADER_START

    // Get current viewport
    int iTempX, iTempY, iWidth, iHeight;
  gcpRendD3D->GetViewport(&iTempX, &iTempY, &iWidth, &iHeight);

  gcpRendD3D->Set2DMode(false, 1, 1);       

  float fAmount = m_pAmount->GetParam();
  float fWatLevel = SPostEffectsUtils::m_fWaterLevel;

  static CCryNameTSCRC pTechName("UnderwaterGodRays");
  static CCryNameR pParam0Name("PI_GodRaysParamsVS");
  static CCryNameR pParam1Name("PI_GodRaysParamsPS");

  //////////////////////////////////////////////////////////////////////////////////////////////////
  // Render god-rays into low-res render target for less fillrate hit




	gcpRendD3D->FX_PushRenderTarget(0,  CTexture::s_ptexBackBufferScaled[1], 0); 
  gcpRendD3D->RT_SetViewport(0, 0, CTexture::s_ptexBackBufferScaled[1]->GetWidth(), CTexture::s_ptexBackBufferScaled[1]->GetHeight());        

  ColorF clearColor(0, 0, 0, 0);
  gcpRendD3D->EF_ClearBuffers(FRT_CLEAR_COLOR|FRT_CLEAR_IMMEDIATE, &clearColor);

  //  PostProcessUtils().ShBeginPass(CShaderMan::m_shPostEffects, pTechName, FEF_DONTSETSTATES);   
  uint32 nPasses;
  CShaderMan::m_shPostEffects->FXSetTechnique(pTechName);
  CShaderMan::m_shPostEffects->FXBegin(&nPasses, FEF_DONTSETSTATES);

  int nSlicesCount = 10;   
  bool bInVisarea = (gRenDev->m_p3DEngineCommon.m_pCamVisAreaInfo.nFlags & S3DEngineCommon::VAF_EXISTS_FOR_POSITION);
  Vec3 vSunDir = bInVisarea? Vec3(0.5f,0.5f,1.0f) :  -gEnv->p3DEngine->GetSunDirNormalized();

  for( int r(0); r < nSlicesCount; ++r)   
  {
    // !force updating constants per-pass!
    CShaderMan::m_shPostEffects->FXBeginPass(0);

    // Set per instance params  
    Vec4 pParams= Vec4(fWatLevel, fAmount, r, 1.0f / (float) nSlicesCount);
    CShaderMan::m_shPostEffects->FXSetVSFloat(pParam0Name, &pParams, 1);

    CShaderMan::m_shPostEffects->FXSetPSFloat(pParam1Name, &pParams, 1);

    gcpRendD3D->SetCullMode( R_CULL_NONE );
    gcpRendD3D->FX_SetState(GS_BLSRC_ONE | GS_BLDST_ONE | GS_NODEPTHTEST);

		PostProcessUtils().DrawFullScreenQuad(CTexture::s_ptexBackBuffer->GetWidth(), CTexture::s_ptexBackBuffer->GetHeight(), 0, false);

    CShaderMan::m_shPostEffects->FXEndPass();
  }


  CShaderMan::m_shPostEffects->FXEnd(); 

  //  PostProcessUtils().ShEndPass(); 

  gcpRendD3D->Set2DMode(true, 1, 1);       

  // Restore previous viewport
  gcpRendD3D->FX_PopRenderTarget(0);
  gcpRendD3D->RT_SetViewport(iTempX, iTempY, iWidth, iHeight);      





  //////////////////////////////////////////////////////////////////////////////////////////////////
  // Display god-rays

  CCryNameTSCRC pTechName0("UnderwaterGodRaysFinal");

  PostProcessUtils().ShBeginPass(CShaderMan::m_shPostEffects, pTechName0, FEF_DONTSETSTATES);   
  gcpRendD3D->FX_SetState(GS_NODEPTHTEST);

  PostProcessUtils().DrawFullScreenQuad(CTexture::s_ptexBackBuffer->GetWidth(), CTexture::s_ptexBackBuffer->GetHeight()); 
  PostProcessUtils().ShEndPass(); 

  gcpRendD3D->FX_Flush();
  PROFILE_SHADER_END  

    PROFILE_LABEL_POP( "GODRAYS" );
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////

void CWaterDroplets::Render()
{
  gRenDev->m_cEF.mfRefreshSystemShader("PostEffectsGame", CShaderMan::m_shPostEffectsGame);

  static CCryNameTSCRC pTechName("WaterDroplets");
  PostProcessUtils().ShBeginPass(CShaderMan::m_shPostEffectsGame, pTechName, FEF_DONTSETSTATES);   

  gcpRendD3D->FX_SetState(GS_NODEPTHTEST);   

  float fUserAmount = m_pAmount->GetParam();

  float fAtten = clamp_tpl<float>(fabs( gRenDev->GetRCamera().Orig.z - SPostEffectsUtils::m_fWaterLevel ), 0.0f, 1.0f);
  Vec4 vParams=Vec4(1, 1, 1, min(fUserAmount + (1.0f - clamp_tpl<float>(m_fCurrLifeTime, 0.0f, 1.0f)), 1.0f) * fAtten);    
  static CCryNameR pParamName("waterDropletsParams");
  CShaderMan::m_shPostEffectsGame->FXSetPSFloat(pParamName, &vParams, 1);

  PostProcessUtils().DrawFullScreenQuad(CTexture::s_ptexBackBuffer->GetWidth(), CTexture::s_ptexBackBuffer->GetHeight());

  PostProcessUtils().ShEndPass();   
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////

void CWaterFlow::Render()
{
	gRenDev->m_cEF.mfRefreshSystemShader("PostEffectsGame", CShaderMan::m_shPostEffectsGame);

  float fAmount = m_pAmount->GetParam();

  static CCryNameTSCRC pTechName("WaterFlow");
  PostProcessUtils().ShBeginPass(CShaderMan::m_shPostEffectsGame, pTechName, FEF_DONTSETSTATES);   

  gcpRendD3D->FX_SetState(GS_NODEPTHTEST);   

  Vec4 vParams=Vec4(1, 1, 1, fAmount);    
  static CCryNameR pParamName("waterFlowParams");
  CShaderMan::m_shPostEffectsGame->FXSetPSFloat(pParamName, &vParams, 1);

  PostProcessUtils().DrawFullScreenQuad(CTexture::s_ptexBackBuffer->GetWidth(), CTexture::s_ptexBackBuffer->GetHeight());

  PostProcessUtils().ShEndPass();   
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

// Enabled/Disabled if no hits on list to process - call from render thread
bool CWaterRipples::RT_SimulationStatus()
{
	return !s_pWaterHits[gcpRendD3D->m_RP.m_nProcessThreadID].empty();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CWaterRipples::Preprocess()
{
	const float fTimeOut = 3.0f; // 3 seconds
	bool bSimTimeOut = (gEnv->pTimer->GetCurrTime() - m_fLastSpawnTime) > fTimeOut;
	if( !m_bPhysCallbackInitialized || s_nUpdateMask || CRenderer::CV_r_PostProcessGameFx && m_pAmount->GetParam() > 0.005f && (RT_SimulationStatus() || !bSimTimeOut) )
	{
		if( m_bPhysCallbackInitialized == false)
		{
			gEnv->pPhysicalWorld->AddEventClient(EventPhysCollision::id, &OnEventPhysArea, 1);
			m_bPhysCallbackInitialized = true;
		}

		return true;
	}

	//Reset();
	m_bInitializeSim = true;
	m_pAmount->ResetParam(0.0f);
	
	return false;  
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CWaterRipples::AddHit(const Vec3 &vPos)
{
	const uint32 nThreadID = gcpRendD3D->m_RP.m_nFillThreadID;
	s_pWaterHits[nThreadID].push_back( Vec2( vPos.x, vPos.y ) );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CWaterRipples::Reset(bool bOnSpecChange)
{	
	m_fLastSpawnTime = 0.0f;

	if( gEnv->pPhysicalWorld )
		gEnv->pPhysicalWorld->RemoveEventClient(EventPhysCollision::id, &OnEventPhysArea, 1);

	m_bPhysCallbackInitialized = false;
	m_bInitializeSim = true;

	for (int i = 0; i < RT_COMMAND_BUF_COUNT; i++)
		stl::free_container(s_pWaterHits[i]);
	stl::free_container(s_pWaterHitsMGPU);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

int CWaterRipples::OnEventPhysArea(const EventPhys *pEvent)
{
	EventPhysCollision *pEventPhysArea = (EventPhysCollision*)pEvent;
	if( !pEventPhysArea )
		return 1;

	// only add nearby hits
	if( pEventPhysArea->idmat[1]  == gEnv->pPhysicalWorld->GetWaterMat() ) 
		AddHit( pEventPhysArea->pt );

	return 1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CWaterRipples::RenderHits()
{
	const uint32 nThreadID = gcpRendD3D->m_RP.m_nProcessThreadID;

	uint32 nWidth = CTexture::s_ptexWaterRipplesDDN->GetWidth();
	uint32 nHeight = CTexture::s_ptexWaterRipplesDDN->GetHeight();
	float fWidthRcp = 1.0f / (float) nWidth;
	float fHeightRcp = 1.0f / (float) nHeight;
	float fRatio = fHeightRcp / fWidthRcp;

	float fWidthHit = 2.0f * fWidthRcp*fRatio;
	float fHeightHit = 2.0f * fHeightRcp;

	gcpRendD3D->Set2DMode(false, 1, 1);       
	gcpRendD3D->Set2DMode(true, nWidth, nHeight);

	// Add hits to simulation
	PostProcessUtils().ShBeginPass(CShaderMan::m_shPostEffects, m_pRipplesHitTechName, FEF_DONTSETSTATES|FEF_DONTSETTEXTURES);   

	// only update blue channel: current frame
	gcpRendD3D->FX_SetState(GS_BLSRC_ONE | GS_BLDST_ONE | GS_NODEPTHTEST | GS_NOCOLMASK_R|GS_NOCOLMASK_G|GS_NOCOLMASK_A); 

	// Simulation origin point is snapped camera position to nearest m_fSimGridSnapRange
	Vec2 vSimOrig = Vec2( s_CameraPos.x - fabs( fmodf(s_CameraPos.x, m_fSimGridSnapRange) ),
											  s_CameraPos.y - fabs( fmodf(s_CameraPos.y, m_fSimGridSnapRange) ) );

		
	uint32 nHitCount = s_pWaterHitsMGPU.size();
	uint32 nCurrHit = 0;

	for(; nCurrHit<nHitCount; ++nCurrHit )
	{
		Vec2 &pCurr = s_pWaterHitsMGPU[nCurrHit];

		// Map hit world space to simulation space
		float xmapped = (-m_fSimGridSize + vSimOrig.x - pCurr.x) * m_fSimGridSizeRcp * 0.5f + 1.0f;
		float ymapped = (-m_fSimGridSize + vSimOrig.y - pCurr.y) * m_fSimGridSizeRcp * 0.5f + 1.0f;

		// Render a sprite at hit location
		float x0 = (xmapped - 0.5f * fWidthHit)* (float)nWidth;
		float y0 = (ymapped - 0.5f * fHeightHit)* (float)nHeight;

		float x1 = (xmapped + 0.5f * fWidthHit) * (float)nWidth;
		float y1 = (ymapped + 0.5f * fHeightHit) * (float)nHeight;
		
		PostProcessUtils().DrawScreenQuad(nWidth, nHeight, x0, y0, x1, y1);
	}

	PostProcessUtils().ShEndPass(); 

	gcpRendD3D->Set2DMode(false, nWidth, nHeight);
	gcpRendD3D->Set2DMode(true, 1, 1);       
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CWaterRipples::Render()
{	
  if (!CTexture::s_ptexWaterRipplesDDN || !CTexture::IsTextureExist(CTexture::s_ptexBackBufferScaled[0]))
    return;

	const uint32 nThreadID = gRenDev->m_RP.m_nProcessThreadID;
	int32 nGpuID = 0;//gRenDev->RT_GetCurrGpuID();




  
	gRenDev->m_cEF.mfRefreshSystemShader("PostEffectsGame", CShaderMan::m_shPostEffectsGame);

  // Get current viewport
  int iTempX, iTempY, iWidth, iHeight;
  gRenDev->GetViewport(&iTempX, &iTempY, &iWidth, &iHeight);
 
	static float fLastTime = 0.0f;
	float fTime = gRenDev->m_RP.m_TI[nThreadID].m_RealTime;
	
	// only allow updates every 25ms - for lower frames, would need to iterate multiple times 
  if (!gRenDev->IsMultiGPUModeActive())
  {
	  if (fTime - fLastTime < 0.025f) 
		  return;
    fLastTime = fTime - fmodf(fTime - fLastTime, 0.025f);
  }
  else
  {
    if (fTime - fLastTime <= 0.0f) 
      return;
    fLastTime = gRenDev->m_RP.m_TI[nThreadID].m_RealTime;
  }

  Vec4 vParams = Vec4(0,0,0,0);       
	if( !s_pWaterHits[nThreadID].empty())
	{
		vParams = Vec4(s_pWaterHits[nThreadID][0].x, s_pWaterHits[nThreadID][0].y, 0, 1.0f);    
		m_fLastSpawnTime = fTime;
	}
	
  if (!s_nUpdateMask)
  {
    float fSnapSize = 5.0f;
    s_CameraPos = gRenDev->GetRCamera().Orig;

    float x = s_CameraPos.x;
    float y = s_CameraPos.y;

    float fracx = x - ceilf(x / fSnapSize) * fSnapSize;
    float fracy = y - ceilf(y / fSnapSize) * fSnapSize;

    float xsnap = x - fracx;
    float ysnap = y - fracy;

    m_bSnapToCenter = false;
    if (m_vLastSnapPos.x != xsnap || m_vLastSnapPos.y != ysnap)
    {
      m_bSnapToCenter = true;
      vParams.x = 0;
      vParams.y = 0;
      if (m_vLastSnapPos.x != xsnap )
        vParams.x = (xsnap>m_vLastSnapPos.x)?1.0f:-1.0f;
      if (m_vLastSnapPos.y != ysnap )
        vParams.y = (ysnap>m_vLastSnapPos.y)?1.0f:-1.0f;

      m_vLastSnapPos.x = xsnap;
      m_vLastSnapPos.y = ysnap;
    }

    s_bInitializeSim = m_bInitializeSim;
    s_vParams = vParams;
    s_pWaterHitsMGPU = s_pWaterHits[nThreadID];
    if (gRenDev->m_nGPUs > 1)
      s_nUpdateMask = (1<<gRenDev->m_nGPUs)-1;

  }

	PROFILE_LABEL_PUSH( "WATER RIPPLES GEN" );

	uint64 nSaveFlagsShader_RT = gRenDev->m_RP.m_FlagsShader_RT;
	gRenDev->m_RP.m_FlagsShader_RT &= ~(g_HWSR_MaskBit[HWSR_SAMPLE0]|g_HWSR_MaskBit[HWSR_SAMPLE1]);




	// spawn particles into effects accumulation buffer
	gcpRendD3D->FX_PushRenderTarget(0, CTexture::s_ptexBackBufferScaled[0], 0); 
	gcpRendD3D->RT_SetViewport(0, 0, CTexture::s_ptexWaterRipplesDDN->GetWidth(), CTexture::s_ptexWaterRipplesDDN->GetHeight()); 

	if (s_bInitializeSim)
	{
		// Initialize sim on first frame
		ColorF clearColor(0, 0, 0, 0);
		gcpRendD3D->EF_ClearBuffers(FRT_CLEAR_COLOR|FRT_CLEAR_IMMEDIATE, &clearColor);
		m_bInitializeSim = false;
	}

	// Snapping occurred - update simulation to new offset
	if (m_bSnapToCenter)
	{			
		gRenDev->m_RP.m_FlagsShader_RT |= g_HWSR_MaskBit[HWSR_SAMPLE0];						
		
		PostProcessUtils().ShBeginPass(CShaderMan::m_shPostEffects, m_pRipplesGenTechName, FEF_DONTSETSTATES|FEF_DONTSETTEXTURES);   
		gcpRendD3D->FX_SetState(GS_NODEPTHTEST);      

		CShaderMan::m_shPostEffects->FXSetPSFloat(m_pRipplesParamName, &s_vParams, 1);

		PostProcessUtils().SetTexture(CTexture::s_ptexWaterRipplesDDN, 0, FILTER_LINEAR, 1);   
		PostProcessUtils().DrawFullScreenQuad(CTexture::s_ptexWaterRipplesDDN->GetWidth(), CTexture::s_ptexWaterRipplesDDN->GetHeight());

		PostProcessUtils().ShEndPass(); 

		PostProcessUtils().CopyScreenToTexture(CTexture::s_ptexWaterRipplesDDN);

		gRenDev->m_RP.m_FlagsShader_RT &= ~g_HWSR_MaskBit[HWSR_SAMPLE0];
	}
	
  // Compute wave propagation
  PostProcessUtils().ShBeginPass(CShaderMan::m_shPostEffects, m_pRipplesGenTechName, FEF_DONTSETSTATES|FEF_DONTSETTEXTURES);   
  gcpRendD3D->FX_SetState(GS_NODEPTHTEST);      

  CShaderMan::m_shPostEffects->FXSetPSFloat(m_pRipplesParamName, &s_vParams, 1);

  PostProcessUtils().SetTexture(CTexture::s_ptexWaterRipplesDDN, 0, FILTER_LINEAR, 1);   
  PostProcessUtils().DrawFullScreenQuad(CTexture::s_ptexWaterRipplesDDN->GetWidth(), CTexture::s_ptexWaterRipplesDDN->GetHeight());
  PostProcessUtils().ShEndPass(); 

	// Add current frame hits
	RenderHits();
	
	PostProcessUtils().CopyScreenToTexture(CTexture::s_ptexWaterRipplesDDN);

	CTexture::s_ptexBackBufferScaled[0]->SetResolved(true);
  gcpRendD3D->FX_PopRenderTarget(0);    

	CTexture::s_ptexWaterRipplesDDN->GenerateMipMaps();





  gcpRendD3D->RT_SetViewport(0, 0, iWidth, iHeight);        
	
  // disable processing
  m_pAmount->SetParam(0.0f);
	gRenDev->m_RP.m_FlagsShader_RT = nSaveFlagsShader_RT;

  s_nUpdateMask &= ~(1<<gRenDev->RT_GetCurrGpuID());
  s_pWaterHits[nThreadID].clear();

  PROFILE_LABEL_POP( "WATER RIPPLES GEN" );
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////

namespace WaterVolumeStaticData
{
	CWater *pWaterSim = 0;
	void GetMemoryUsage( ICrySizer *pSizer )
	{
		if( pWaterSim )
			pWaterSim->GetMemoryUsage(pSizer);
	}
}

void CWaterVolume::Render()
{
	gRenDev->m_cEF.mfRefreshSystemShader("PostEffectsGame", CShaderMan::m_shPostEffectsGame);

  {
    static int nFrameID = 0;

		// remember ptr of WaterSim to access it with CrySizer
		WaterVolumeStaticData::pWaterSim = WaterSimMgr();

    const int nGridSize = 64;

    int nCurFrameID = gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_nFrameID;
    if( nFrameID != nCurFrameID )
    {
      static Vec4 pParams0(0, 0, 0, 0), pParams1(0, 0, 0, 0);
      Vec4 pCurrParams0, pCurrParams1;
      gEnv->p3DEngine->GetOceanAnimationParams(pCurrParams0, pCurrParams1);

      // Update sim settings
      if( WaterSimMgr()->NeedInit() || pCurrParams0.x != pParams0.x || pCurrParams0.y != pParams0.y ||
        pCurrParams0.z != pParams0.z || pCurrParams0.w != pParams0.w || pCurrParams1.x != pParams1.x || 
        pCurrParams1.y != pParams1.y || pCurrParams1.z != pParams1.z || pCurrParams1.w != pParams1.w )
      {
        pParams0 = pCurrParams0;
        pParams1 = pCurrParams1;
				WaterSimMgr()->Create( 1.0, pParams0.x, pParams0.z, 1.0f, 1.0f);        
      }

      // Create texture if required
      if (!CTexture::IsTextureExist(CTexture::s_ptexWaterVolumeTemp))
      {
				ScopedSwitchToGlobalHeap globalHeap;
        if(!CTexture::s_ptexWaterVolumeTemp->Create2DTexture(64, 64, 1, 
          FT_DONT_RELEASE | FT_NOMIPS |  FT_USAGE_DYNAMIC, 
          0, eTF_A32B32G32R32F, eTF_A32B32G32R32F))
					return;
        CTexture::s_ptexWaterVolumeTemp->Fill(ColorF(0, 0, 0, 0));
      }

			CTexture *pTexture = CTexture::s_ptexWaterVolumeTemp;

      // Copy data..
      if (CTexture::IsTextureExist(pTexture))
      {
				//const float fUpdateTime = 2.f*0.125f*gEnv->pTimer->GetCurrTime();
				const float fUpdateTime = 0.125*gEnv->pTimer->GetCurrTime();// / clamp_tpl<float>(pParams1.x, 0.55f, 1.0f);
				
				void *pRawPtr = NULL;



				WaterSimMgr()->Update(nCurFrameID, fUpdateTime, true, pRawPtr);
			
#if !defined(PS3) // if not running PS3, we need to update the texture in the calling thread context
        Vec4 *pDispGrid = WaterSimMgr()->GetDisplaceGrid();

        uint32 pitch = 4 * sizeof( float )*nGridSize; 
        uint32 width = nGridSize; 
        uint32 height = nGridSize;
















        STALL_PROFILER("update subresource")

        CDeviceTexture* pDevTex = pTexture->GetDevTexture();
        assert(pDevTex);












        STexLock rect;
        if (SUCCEEDED(pDevTex->LockRect(0, rect, LF_DISCARD))) //
        {
          cryMemcpy(rect.pData, pDispGrid, width * height* sizeof(Vec4) );
          pDevTex->UnlockRect(0);
        }


#endif
      }
      nFrameID = nCurFrameID;
    }
  }
  // Get current viewport
  int iTempX, iTempY, iWidth, iHeight;
  gcpRendD3D->GetViewport(&iTempX, &iTempY, &iWidth, &iHeight);





  // make final normal map
  gcpRendD3D->FX_PushRenderTarget(0, CTexture::s_ptexWaterVolumeDDN, NULL); 
  gcpRendD3D->RT_SetViewport(0, 0, CTexture::s_ptexWaterVolumeDDN->GetWidth(), CTexture::s_ptexWaterVolumeDDN->GetHeight()); 

  static CCryNameTSCRC pTechName("WaterVolumesNormalGen");
  PostProcessUtils().ShBeginPass(CShaderMan::m_shPostEffectsGame, pTechName, FEF_DONTSETSTATES|FEF_DONTSETTEXTURES);   
  gcpRendD3D->FX_SetState(GS_NODEPTHTEST);   

  static CCryNameR pParamName("waterVolumesParams");
  Vec4 vParams = Vec4(64.0f, 64.0f, 64.0f, 64.0f);    
  CShaderMan::m_shPostEffectsGame->FXSetPSFloat(pParamName, &vParams, 1);

  int32 nFilter = FILTER_LINEAR;



  
  PostProcessUtils().SetTexture(CTexture::s_ptexWaterVolumeTemp, 0, nFilter, 0);   
  PostProcessUtils().DrawFullScreenQuad(CTexture::s_ptexBackBuffer->GetWidth(), CTexture::s_ptexBackBuffer->GetHeight());

  PostProcessUtils().ShEndPass(); 

  gcpRendD3D->FX_PopRenderTarget(0);    
  gcpRendD3D->RT_SetViewport(0, 0, iWidth, iHeight);      

	CTexture::s_ptexWaterVolumeDDN->GenerateMipMaps();





		
	// HACK (re-set back-buffer): due to lazy RT updates/setting there's strong possibility we run into problems on x360 when we try to resolve from edram with no RT set
	gcpRendD3D->FX_SetActiveRenderTargets();
	gcpRendD3D->FX_ResetPipe();
	
  // disable processing
  m_pAmount->SetParam(0.0f);	
}
